	/*
   * Copyright (c) 2024 iSoftStone Education Co., Ltd.
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *	 http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
#include <stdio.h>
#include "ohos_init.h"
#include "cmsis_os2.h"
#include "los_task.h"
#include "config_network.h"
#include "lwip/tcp.h"
#include "lwip/ip_addr.h"
#include "lwip/priv/tcp_priv.h"
#include "lwip/stats.h"
#include "lwip/inet_chksum.h"
#include "aht20.h"
#include "cJSON.h"
#include "lm2904_driver.h"
#include <stdint.h>
#include <math.h>
#include "iot_adc.h"
#include "iot_errno.h"
#include "mq135.h"
#include <time.h>
#include "moisture_sensor.h"
#include "wind_direction.h"
#include "wind_speed.h"
  
  
  int id=1;
#define LOG_TAG    "tcp"
  int get_wifi_info(WifiLinkedInfo *info);
  
  // #define OC_SERVER_IP	"192.168.156.51"
  // #define SERVER_PORT 7777
  
  
#define ROUTE_SSID "xuanlingjing"
#define ROUTE_PASSWORD "xuanlingjing2315"
#define OC_SERVER_IP   "192.168.136.84"
#define SERVER_PORT 6666
#define BUFF_LEN    256
#define MSG_QUEUE_LENGTH    16
  static unsigned int m_msg_queue;
  // 修改为包含 7 个元素，分别为温度、湿度、土壤湿度、风速、风向、噪声、空气质量
  double sensor_data[7] = {0};
  
  // 函数声明
  double read_temperature();
  double read_humidity();
  double read_soil_moisture();
  double read_wind_speed();
  double read_wind_direction();
  double read_noise();
  double read_air_quality();
  
  
  // #define ROUTE_SSID "401"
  // #define ROUTE_PASSWORD "11223344"
  
  int get_wifi_info(WifiLinkedInfo *info)
  {
	  int ret = -1;
	  int gw, netmask;
	  memset(info, 0, sizeof(WifiLinkedInfo));
	  unsigned int retry = 15;
	  while (retry) {
		  if (GetLinkedInfo(info) == WIFI_SUCCESS) {
			  if (info->connState == WIFI_CONNECTED) {
				  if (info->ipAddress != 0) {
					  LZ_HARDWARE_LOGD(LOG_TAG, "rknetwork IP (%s)", inet_ntoa(info->ipAddress));
					  if (WIFI_SUCCESS == GetLocalWifiGw(&gw)) {
						  LZ_HARDWARE_LOGD(LOG_TAG, "network GW (%s)", inet_ntoa(gw));
					  }
					  if (WIFI_SUCCESS == GetLocalWifiNetmask(&netmask)) {
						  LZ_HARDWARE_LOGD(LOG_TAG, "network NETMASK (%s)", inet_ntoa(netmask));
					  }
					  if (WIFI_SUCCESS == SetLocalWifiGw()) {
						  LZ_HARDWARE_LOGD(LOG_TAG, "set network GW");
					  }
					  if (WIFI_SUCCESS == GetLocalWifiGw(&gw)) {
						  LZ_HARDWARE_LOGD(LOG_TAG, "network GW (%s)", inet_ntoa(gw));
					  }
					  if (WIFI_SUCCESS == GetLocalWifiNetmask(&netmask)) {
						  LZ_HARDWARE_LOGD(LOG_TAG, "network NETMASK (%s)", inet_ntoa(netmask));
					  }
					  ret = 0;
					  goto connect_done;
				  }
			  }
		  }
		  LOS_Msleep(1000);
		  retry--;
	  }
  
  connect_done:
	  return ret;
  }
  
  
  // 传感器读取函数示例，需要根据实际传感器进行实现
  void read_environment_data() { 
	  aht20_init();
	  // 读取温度
	  sensor_data[0] = read_temperature();
	  // 读取湿度
	  sensor_data[1] = read_humidity();
	  // 读取土壤湿度
	  sensor_data[2] = read_soil_moisture();
	  // 读取风速
	  sensor_data[3] = read_wind_speed();
	  // 读取风向
	  sensor_data[4] = read_wind_direction();
	  // 读取噪声
	  sensor_data[5] = read_noise();
	  // 读取空气质量
	  sensor_data[6] = read_air_quality();
  }
  
  // 模拟传感器读取函数，需要替换为实际的传感器读取代码
  double read_temperature(){
  
	  double aht20_data[2] = {0};
   
	  printf("************ AHT20-Temperature Process ************\n");
  
	  aht20_read_data(aht20_data); // 读取温湿度
  
	  printf("Temperature: %.2f ℃ \n", aht20_data[0]);
  
	  return aht20_data[0];
  
  }
  double read_humidity() {
	  // 实际代码中应实现读取湿度传感器数据
  
	  double aht20_data[2] = {0};
   
	  printf("************ AHT20-Humidity Process ************\n");
  
	  aht20_read_data(aht20_data); // 读取温湿度
  
	  printf("	Humidity: %.2f %%RH\n",  aht20_data[1]);
  
	  return aht20_data[1];
  }
  
  double read_soil_moisture() {
	  // 实际代码中应实现读取土壤湿度传感器数据
	  double moisture = 0;
  
	  /* 初始化土壤湿度传感器 */
	  moisture_sensor_init();
  
	  printf("************ Moisture Sensor Process ************\n");
  
	  /* 读取湿度数据 */
	  moisture_sensor_read_data(&moisture);
  
	  printf("Soil Moisture: %.2f %%\r\n", moisture);
  
	  return moisture;}
  
  double read_wind_speed() {
  	
  	IoTUartDeinit(WIND_SPEED_UART_ID); // 防止占用，重新初始化
	  	  
	  	      IotUartAttribute attr = {
	  	          .baudRate = WIND_SPEED_UART_BAUDRATE,
	  	          .dataBits = IOT_UART_DATA_BIT_8,
	  	          .parity = IOT_UART_PARITY_NONE,
	  	          .stopBits = IOT_UART_STOP_BIT_1,
	  	          .rxBlock = IOT_UART_BLOCK_STATE_BLOCK,
	  	          .txBlock = IOT_UART_BLOCK_STATE_BLOCK,
	  	          .pad = IOT_FLOW_CTRL_NONE,
	  	      };
	  	  
	  	      if (IoTUartInit(WIND_SPEED_UART_ID, &attr) != IOT_SUCCESS)
	  	      {
	  	          printf("[WIND_SPEED] Failed to init UART%d\n", WIND_SPEED_UART_ID);
	  	          return;
	  	      }
	  	  
	  	          float ret =read_wind_speed_data();
	  	      
	  	          return ret;
	  	          // usleep(2000000); // 每2秒读取一次
  	
	  // 实际代码中应实现读取风速传感器数据
//	  return 10.0;
  }
  
  double read_wind_direction() {
	  // 实际代码中应实现读取风向传感器数据
  
  
  
  float ret =  wind_direction_task();
  return ret;
//	  return 180.0;
  }
  
  double read_noise() {
	  // 实际代码中应实现读取噪声传感器数据
	  if (LM2904Init() != IOT_SUCCESS) {
		  printf("[ERR] Driver init failed!\n");
		  return;
	  }
	  float db = GetFilteredNoiseLevel();
		  if (isnan(db)) {
			  printf("[ERR] Read failed!\n");
		  } else {
			  printf("Noise: %.1f dB\n", db);
			  return db;
		  }
  }
  
  double read_air_quality() {
	  // 实际代码中应实现读取空气质量传感器数据
  
	  double ppm_data = 0;
	  /* 初始化MQ135传感器 */
	  mq135_init();
		  printf("************ MQ135 Process ************\n");
  
		  /* 读取MQ135数据 */
		  mq135_read_data(&ppm_data);
  
		  printf("Gas concentration: %.2f ppm \r\n", ppm_data);
  
		  // double g_ppm = ppm_data;  // 存储气体浓度
  
		  printf("\r\n");
  
		  LOS_Msleep(1000);  // 每秒钟读取一次数据
		  return ppm_data;
  }
  
  
  // 环境数据读取线程
  void environment_read_thread(void *arg) {
	  unsigned int ret = LOS_OK;
	  while (1) {
		  read_environment_data();
		  // printf("%.2f,%.2f,%.2f,%.2f",sensor_data[0], sensor_data[1], sensor_data[2], sensor_data[3]);
		  ret=LOS_QueueWrite(m_msg_queue, (void *)&sensor_data, sizeof(sensor_data), LOS_WAIT_FOREVER);
		  if (LOS_OK != ret)
		  {
			  printf("%s write Message Queue msg fail ret:0x%x\n", __func__, ret);
		  }
		  else
		  {
			  printf("%s write Message Queue msg:%.2f\n", __func__, sensor_data[0]);
		  }
		  LOS_Msleep(10500);
	  }
  }
  void tcp_send_data(int client_fd,double* tmp) {
	  double* data=tmp;
	  cJSON *root = cJSON_CreateObject();
	  
	  cJSON_AddNumberToObject(root, "id", id++);
  
	  // 添加时间信息
	  time_t rawtime;
	  struct tm * timeinfo;
	  time(&rawtime);
	  timeinfo = localtime(&rawtime);
	  char time_str[80];
	  strftime(time_str, 80, "%H:%M:%S", timeinfo);
	  cJSON_AddStringToObject(root, "time", time_str);
  
	  // 将传感器数据转换为字符串后添加到 JSON
	  char temp_str[20];
	  snprintf(temp_str, sizeof(temp_str), "%.2f", data[0]);
	  cJSON_AddStringToObject(root, "Temp", temp_str);
  
	  char hum_str[20];
	  snprintf(hum_str, sizeof(hum_str), "%.2f", data[1]);
	  cJSON_AddStringToObject(root, "Hum", hum_str);
  
	  char soil_str[20];
	  snprintf(soil_str, sizeof(soil_str), "%.2f", data[2]);
	  cJSON_AddStringToObject(root, "Soil", soil_str);
  
	  char wind_str[20];
	  snprintf(wind_str, sizeof(wind_str), "%.2f", data[3]);
	  cJSON_AddStringToObject(root, "Wind", wind_str);
  
	  char direction_str[20];
	  snprintf(direction_str, sizeof(direction_str), "%.2f", data[4]);
	  cJSON_AddStringToObject(root, "Direction", direction_str);
  
	  char noise_str[20];
	  snprintf(noise_str, sizeof(noise_str), "%.2f", data[5]);
	  cJSON_AddStringToObject(root, "Noise", noise_str);
  
	  char pm_str[20];
	  snprintf(pm_str, sizeof(pm_str), "%.2f", data[6]);
	  cJSON_AddStringToObject(root, "PM", pm_str);
  
	  char *json_str = cJSON_Print(root);
	  if (json_str != NULL) {
		  int count = send(client_fd, json_str, strlen(json_str), 0);
		  if (count == -1) {
			  printf("[tcp server] send data fail!\n");
		  } else {
			  printf("[tcp server] send msg: %s\n", json_str);
		  }
		  free(json_str);
	  } else {
  
		  printf("[tcp server] Failed to create JSON string!\n");
	  }
  
	  cJSON_Delete(root);
  }
  
  
  void tcp_server_msg_handle(int fd)
  {
	  char buf[BUFF_LEN];  //接收缓冲区
	  socklen_t client_addr_len;
	  int cnt = 0, count;
	  int client_fd;
	  struct sockaddr_in client_addr = {0};
	  
	  printf("waitting for client connect...\n");
	  /* 监听socket 此处会阻塞 */
	  client_fd = accept(fd, (struct sockaddr*)&client_addr, &client_addr_len);
	  // client_fd = lwip_accept(fd, (struct sockaddr*)&client_addr, &client_addr_len);
	  printf("[tcp server] accept <%s:%d>\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
	  // while (1)
	  // {
	  //	 memset(buf, 0, BUFF_LEN);
	  //	 printf("-------------------------------------------------------\n");
	  //	 printf("[tcp server] waitting client msg\n");
	  //	 count = recv(client_fd, buf, BUFF_LEN, 0); 	  //read是阻塞函数，没有数据就一直阻塞
	  //	 // count = lwip_read(client_fd, buf, BUFF_LEN);  //read是阻塞函数，没有数据就一直阻塞
	  //	 if (count == -1)
	  //	 {
	  //		 printf("[tcp server] recieve data fail!\n");
	  //		 LOS_Msleep(3000);
	  //		 break;
	  //	 }
	  //	 printf("[tcp server] rev client msg:%s\n", buf);
	  //	 memset(buf, 0, BUFF_LEN);
	  //	 sprintf(buf, "I have recieved %d bytes data! recieved cnt:%d", count, ++cnt);
	  //	 printf("[tcp server] send msg:%s\n", buf);
	  //	 send(client_fd, buf, strlen(buf), 0);		  //发送信息给client
	  //	 // lwip_write(client_fd, buf, strlen(buf));  //发送信息给client
	  // }
  
	  // double *data_ptr = NULL;
	  // while (1) {
	  //	 LOS_QueueRead(m_msg_queue, (void *)&data_ptr, sizeof(sensor_data), LOS_WAIT_FOREVER);
	  //	 // ret = LOS_QueueCreate("queue", MSG_QUEUE_LENGTH, &m_msg_queue, 0, BUFFER_LEN);
  
	  //	 tcp_send_data(client_fd,  data_ptr);
	  //	 LOS_Msleep(500);
	  // }
  
	  double data_buffer[7]={0};
	  unsigned int ret = LOS_OK;
  
	  while (1) {
		
		  ret=LOS_QueueRead(m_msg_queue, (void *)&data_buffer, sizeof(sensor_data), LOS_WAIT_FOREVER);
		  if (ret == LOS_OK)
		  {
			  printf("%s read Message Queue msg:%.2f\n", __func__, data_buffer[0]);
  
		  }
		  else
		  {
			  printf("%s read Message Queue fail ret:0x%x\n", __func__, ret);
		  }
		  
  
		  tcp_send_data(client_fd, data_buffer);
		  LOS_Msleep(2);
	  }
	  lwip_close(client_fd);
	  lwip_close(fd);
  }
  
  int wifi_server(void* arg)
  {
	  int server_fd, ret;
  
	  while(1)
	  {
		  server_fd = socket(AF_INET, SOCK_STREAM, 0);		   //AF_INET:IPV4;SOCK_STREAM:TCP
		  // server_fd = lwip_socket(AF_INET, SOCK_STREAM, 0); //AF_INET:IPV4;SOCK_STREAM:TCP
		  if (server_fd < 0)
		  {
			  printf("create socket fail!\n");
			  return -1;
		  }
  
		  /*设置调用close(socket)后,仍可继续重用该socket。调用close(socket)一般不会立即关闭socket，而经历TIME_WAIT的过程。*/
		  int flag = 1;
		  ret = setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(int));
		  if (ret != 0) {
			  printf("[CommInitTcpServer]setsockopt fail, ret[%d]!\n", ret);
		  }
		  
		  struct sockaddr_in serv_addr = {0};
		  serv_addr.sin_family = AF_INET;
		  serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); //IP地址，需要进行网络序转换，INADDR_ANY：本地地址
		  // serv_addr.sin_addr.s_addr = inet_addr(OC_SERVER_IP); //IP地址，需要进行网络序转换，INADDR_ANY：本地地址
		  serv_addr.sin_port = htons(SERVER_PORT);		 //端口号，需要网络序转换
		  /* 绑定服务器地址结构 */
		  ret = bind(server_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
		  // ret = lwip_bind(server_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
		  if (ret < 0)
		  {
			  printf("socket bind fail!\n");
			  lwip_close(server_fd);
			  return -1;
		  }
		  /* 监听socket 此处不阻塞 */
		  ret = listen(server_fd, 64);
		  // ret = lwip_listen(server_fd, 64);
		  if(ret != 0)
		  {
			  printf("socket listen fail!\n");
			  lwip_close(server_fd);
			  return -1;
		  }
		  printf("[tcp server] listen:%d<%s:%d>\n",server_fd, inet_ntoa(serv_addr.sin_addr), ntohs(serv_addr.sin_port));
		  tcp_server_msg_handle(server_fd);   //处理接收到的数据
		  LOS_Msleep(1000);
	  }
  }
  
  void tcp_client_msg_handle(int fd, struct sockaddr* dst)
  {
	  socklen_t len = sizeof(*dst);
  
	  int cnt = 0, count = 0;
	  while (connect(fd, dst, len) < 0)
	  {
		  printf("connect server failed...%d\n", ++count);
		  lwip_close(fd);
		  LOS_Msleep(5000);
		  fd = socket(AF_INET, SOCK_STREAM, 0); //AF_INET:IPV4;SOCK_STREAM:TCP
	  }
	  double *data_buffer=NULL; //用于存储从队列读取的数据
	  unsigned int ret = LOS_OK;
	  while (1)
	  {
		  ret = LOS_QueueRead(m_msg_queue, (void *)&data_buffer, sizeof(sensor_data), LOS_WAIT_FOREVER);
		  if (ret == LOS_OK)
		  {
			  printf("%s read Message Queue msg:%.2f\n", __func__, data_buffer[0]);
  
			  tcp_send_data(fd, data_buffer);
		  }
		  else
		  {
			  printf("%s read Message Queue fail ret:0x%x\n", __func__, ret);
		  }
		  LOS_Msleep(2);
	  }
	  lwip_close(fd);
  }
  
  int wifi_client(void* arg)
  {
	  int client_fd, ret;
	  struct sockaddr_in serv_addr;
	  
	  while(1)
	  {
		  client_fd = socket(AF_INET, SOCK_STREAM, 0);//AF_INET:IPV4;SOCK_STREAM:TCP
		  if (client_fd < 0)
		  {
			  printf("create socket fail!\n");
			  return -1;
		  }
  
		  /*设置调用close(socket)后,仍可继续重用该socket。调用close(socket)一般不会立即关闭socket，而经历TIME_WAIT的过程。*/
		  int flag = 1;
		  ret = setsockopt(client_fd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(int));
		  if (ret != 0) {
			  printf("[CommInitTcpServer]setsockopt fail, ret[%d]!\n", ret);
		  }
		  
		  memset(&serv_addr, 0, sizeof(serv_addr));
		  serv_addr.sin_family = AF_INET;
		  serv_addr.sin_addr.s_addr = inet_addr(OC_SERVER_IP);
		  serv_addr.sin_port = htons(SERVER_PORT);
		  printf("[tcp client] connect:%d<%s:%d>\n",client_fd, inet_ntoa(serv_addr.sin_addr), ntohs(serv_addr.sin_port));
		  
		  
		  tcp_client_msg_handle(client_fd, (struct sockaddr*)&serv_addr);
		  
		  LOS_Msleep(1000);
	  }
  
	  return 0;
  }
  
  
  void wifi_process(void *args)
  {
	  unsigned int threadID_client, threadID_server;
	  unsigned int ret = LOS_OK;
	 
	  WifiLinkedInfo info;
  
	  uint8_t mac_address[6] = {0x00, 0xdc, 0xb6, 0x90, 0x00, 0x00};
  
	  FlashInit();
	  VendorSet(VENDOR_ID_WIFI_MODE, "STA", 3); // 配置为Wifi STA模式
	  VendorSet(VENDOR_ID_MAC, mac_address,
				  6); // 多人同时做该实验，请修改各自不同的WiFi MAC地址
	  VendorSet(VENDOR_ID_WIFI_ROUTE_SSID, ROUTE_SSID, sizeof(ROUTE_SSID));
	  VendorSet(VENDOR_ID_WIFI_ROUTE_PASSWD, ROUTE_PASSWORD,
				  sizeof(ROUTE_PASSWORD));
  
	  SetWifiModeOff();
	  SetWifiModeOn();
  
	  while(get_wifi_info(&info) != 0) ;
  
	  CreateThread(&threadID_client,  wifi_client, NULL, "client@ process");
	  // CreateThread(&threadID_server,  wifi_server, NULL, "server@ process");
  }
  
  
  void environment_monitor_example1(void)
  {
	  // unsigned int ret = LOS_OK;
	  // unsigned int thread_id;
	  // TSK_INIT_PARAM_S task = {0};
	  // printf("%s start ....\n", __FUNCTION__);
  
	  unsigned int thread_id_1;
	  unsigned int thread_id_2;
	  TSK_INIT_PARAM_S task_1 = {0};
	  TSK_INIT_PARAM_S task_2 = {0};
	  unsigned int ret = LOS_OK;
	  printf("%s start ....\n", __FUNCTION__);
  
	  ret = LOS_QueueCreate("queue", MSG_QUEUE_LENGTH, &m_msg_queue, 0, sizeof(sensor_data));
	  if (ret != LOS_OK) {
		  printf("Failed to create Message Queue ret:0x%x\n", ret);
		  return;
	  }
  
	  task_1.pfnTaskEntry = (TSK_ENTRY_FUNC)environment_read_thread;
	  task_1.uwStackSize = 2048;
	  task_1.pcName = "environment read thread";
	  task_1.usTaskPrio = 24;
	  ret = LOS_TaskCreate(&thread_id_1, &task_1);
	  if (ret != LOS_OK) {
		  printf("Failed to create task ret:0x%x\n", ret);
		  return;
	  }
  
  
	  task_2.pfnTaskEntry = (TSK_ENTRY_FUNC)wifi_process;
	  task_2.uwStackSize = 10240;
	  task_2.pcName = "wifi_process";
	  task_2.usTaskPrio = 26;
	  ret = LOS_TaskCreate(&thread_id_2, &task_2);
	  if (ret != LOS_OK)
	  {
		  printf("Falied to create wifi_process ret:0x%x\n", ret);
		  return;
	  }
	  
  
	  
	  //创建线程模板
	  // task.pfnTaskEntry = (TSK_ENTRY_FUNC)wifi_process;
	  // task.uwStackSize = 10240;
	  // task.pcName = "wifi_process";
	  // task.usTaskPrio = 24;
	  // ret = LOS_TaskCreate(&thread_id, &task);
	  // if (ret != LOS_OK)
	  // {
	  //	 printf("Falied to create wifi_process ret:0x%x\n", ret);
	  //	 return;
	  // }
  }
  
  APP_FEATURE_INIT(environment_monitor_example1);
  
